package com.tpvlog.im.sdk.android;

import com.tpvlog.im.common.Constants;
import com.tpvlog.im.common.Request;
import com.tpvlog.im.protocal.AuthenticateRequestProto;
import com.tpvlog.im.protocal.MessageSendRequestProto;
import io.netty.bootstrap.Bootstrap;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelOption;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioSocketChannel;
import io.netty.handler.codec.DelimiterBasedFrameDecoder;

/**
 * IM客户端
 */
public class ImClient {
    private EventLoopGroup eventLoopGroup;
    private Bootstrap bootstrap;
    private volatile Boolean isAuthConnected = false;

    public ImClient() {
        this.eventLoopGroup = new NioEventLoopGroup();
        this.bootstrap = new Bootstrap();
        this.bootstrap.group(eventLoopGroup)
                .channel(NioSocketChannel.class)
                .option(ChannelOption.TCP_NODELAY, true)
                .option(ChannelOption.SO_KEEPALIVE, true)
                .handler(new ChannelInitializer<SocketChannel>() {
                    @Override
                    protected void initChannel(SocketChannel socketChannel) throws Exception {
                        ByteBuf delimiter = Unpooled.copiedBuffer(Constants.DELIMITER);
                        socketChannel.pipeline().addLast(new DelimiterBasedFrameDecoder(4096, delimiter));
                        socketChannel.pipeline().addLast(new ImClientHandler(ImClient.this));
                    }
                });
    }

    /**
     * 与目标主机建立连接
     *
     * @param dstHost
     * @param dstPort
     * @throws Exception
     */
    public void connect(String dstHost, int dstPort) throws Exception {
        System.out.println("发起对IM-GATEWAY的连接......");
        // 连接完成后main线程会阻塞在这里
        ChannelFuture channelFuture = this.bootstrap.connect(dstHost, dstPort).sync();;

        // 关闭客户端
        channelFuture.channel().closeFuture().sync();
    }

    /**
     * 发起token认证
     *
     * @param uid
     * @param token
     * @throws Exception
     */
    public void authenticate(String uid, String token) throws Exception {
        // 1.封装认证请求的消息体
        AuthenticateRequestProto.AuthenticateRequest.Builder builder = AuthenticateRequestProto.AuthenticateRequest.newBuilder();
        builder.setUid(uid);
        builder.setToken(token);
        builder.setTimestamp(System.currentTimeMillis());
        AuthenticateRequestProto.AuthenticateRequest authenticateRequest = builder.build();

        // 2.封装一个完整的请求消息
        Request request = new Request(
                Constants.APP_SDK_VERSION_1,
                Constants.REQUEST_TYPE_AUTHENTICATE,
                Constants.SEQUENCE_DEFAULT,
                authenticateRequest.toByteArray());
        System.out.println("向IM-GATEWAY发起用户认证请求");

        // 3.发送请求
        socketChannel.writeAndFlush(request.getBuffer());

        // 4.等待完成认证
        while (isAuthConnected) {
            Thread.sleep(100);
        }
    }

    /**
     * 关闭连接
     *
     * @throws Exception
     */
    public void close() {
        try {
            this.socketChannel.close();
            this.eventLoopGroup.shutdownGracefully();
        } catch (Exception ex) {
            ex.printStackTrace();
        }
    }

    /**
     * 发送单聊消息
     *
     * @param senderId
     * @param receiverId
     * @param content
     */
    public void sendMessage(String senderId, String receiverId, String content) {
        // 1.封装单聊请求的消息体
        MessageSendRequestProto.MessageSendRequest.Builder builder =
                MessageSendRequestProto.MessageSendRequest.newBuilder();
        builder.setSenderId(senderId);
        builder.setReceiverId(receiverId);
        builder.setContent(content);
        MessageSendRequestProto.MessageSendRequest messageSendRequest = builder.build();

        // 2.封装一个完整的请求消息
        Request request = new Request(
                Constants.APP_SDK_VERSION_1,
                Constants.REQUEST_TYPE_SEND_MESSAGE,
                Constants.SEQUENCE_DEFAULT,
                messageSendRequest.toByteArray()
        );

        // 3.发送请求
        System.out.println("客户端向IM-GATEWAY接入系统发送一条单聊消息，" + messageSendRequest);
        socketChannel.writeAndFlush(request.getBuffer());
    }

    public void setAuthConnected(Boolean authConnected) {
        isAuthConnected = authConnected;
    }
}
